package com.slipper.system.menu.controller;

import com.google.gson.reflect.TypeToken;
import com.slipper.common.bo.UserDetail;
import com.slipper.constants.Constants;
import com.slipper.core.tree.Tree;
import com.slipper.exception.NotLoginException;
import com.slipper.core.gson.GsonUtil;
import com.slipper.system.subsystem.bo.SubsystemBO;
import com.slipper.system.subsystem.service.SubsystemService;
import com.slipper.util.*;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.util.*;

import com.slipper.system.menu.bo.MenuBO;
import com.slipper.system.menu.service.MenuService;
import com.slipper.core.tree.TreeInfo;
import com.slipper.core.tree.TreeUtil;

/**
 * 菜单信息表
 */
@RestController
@RequestMapping("/system/menu")
public class MenuController {
    private static final Logger logger = LoggerFactory.getLogger(MenuController.class);

    @Resource
    private MenuService menuService;
    @Resource
    private SubsystemService subsystemService;

    @PostMapping("/queryPage")
    public String queryPage(@RequestBody MenuBO bo) {
        return ResultUtil.successResult(menuService.queryPage(bo));
    }

    @PostMapping("/queryMenuTree")
    public String queryMenuTree() {
        UserDetail userDetail = Constants.getCurrentUser();
        if (userDetail == null) {
            throw new NotLoginException();
        }

        if (!userDetail.isSuperAdmin()) {
            return ResultUtil.failureResult("500", "权限不足！");
        }

        MenuBO menuBO = new MenuBO();
        menuBO.setSubsystem(Constants.Subsystem.TYPE_MANAGE);
        menuBO.setEmployeeId(userDetail.getEmployeeId());
        List<MenuBO> menuList = this.menuService.queryUserMenus(menuBO);

        TreeInfo treeInfo = new TreeInfo("菜单树");
        treeInfo.setRootId(Constants.ROOT_ID);
        treeInfo.setIdField("id");
        treeInfo.setPidField("parentId");
        treeInfo.setTextField("name");
        treeInfo.setHrefField("vuePath");
        treeInfo.setSortField("ordinal");
        return ResultUtil.successResult(TreeUtil.buildTree(treeInfo, menuList));
    }

    @PostMapping("/queryTree")
    public String queryTree(@RequestBody MenuBO bo) {
        List<MenuBO> menuList = menuService.queryList(bo);
        TreeInfo treeInfo = new TreeInfo("菜单树");
        treeInfo.setRootId(Constants.ROOT_ID);
        treeInfo.setIdField("id");
        treeInfo.setPidField("parentId");
        treeInfo.setTextField("name");
        treeInfo.setSortField("ordinal");
        return ResultUtil.successResult(TreeUtil.buildTree(treeInfo, menuList));
    }

    @PostMapping("/querySubsystemTree")
    public String querySubsystemTree() {
        TreeInfo subsystemInfo = new TreeInfo("子系统");
        subsystemInfo.setRootId(Constants.ROOT_ID);
        subsystemInfo.setIdField("id");
        subsystemInfo.setTextField("name");
        subsystemInfo.setSortField("ordinal");

        SubsystemBO subsystemQO = new SubsystemBO();
        subsystemQO.setType(Constants.Subsystem.TYPE_SUBSYSTEM);
        subsystemQO.setValid(Constants.VALID);
        List<SubsystemBO> subsystemList = subsystemService.queryList(subsystemQO);

        TreeInfo portalInfo = new TreeInfo("门户端");
        portalInfo.setRootId(Constants.ROOT_ID);
        portalInfo.setIdField("id");
        portalInfo.setTextField("name");
        portalInfo.setSortField("ordinal");

        SubsystemBO portalQO = new SubsystemBO();
        portalQO.setType(Constants.Subsystem.TYPE_PORTAL);
        portalQO.setValid(Constants.VALID);
        List<SubsystemBO> portalList = subsystemService.queryList(portalQO);

        TreeInfo menuInfo = new TreeInfo("菜单树");
        menuInfo.setRootId(Constants.ROOT_ID);
        menuInfo.setIdField("id");
        menuInfo.setPidField("parentId");
        menuInfo.setTextField("name");
        menuInfo.setSortField("ordinal");

        MenuBO subsystemMenuQO = new MenuBO();
        subsystemMenuQO.setValid(Constants.VALID);
        subsystemMenuQO.setSubsystem(Constants.Subsystem.TYPE_SUBSYSTEM);
        List<MenuBO> subsystemMenuList = menuService.queryList(subsystemMenuQO);
        subsystemMenuList.forEach(menu -> {
            if (Constants.ROOT_ID.equals(menu.getParentId())) {
                menu.setParentId(menu.getSubsystemId());
            }
        });

        MenuBO portalMenuQO = new MenuBO();
        portalMenuQO.setValid(Constants.VALID);
        portalMenuQO.setSubsystem(Constants.Subsystem.TYPE_PORTAL);
        List<MenuBO> portalMenuList = menuService.queryList(portalMenuQO);
        portalMenuList.forEach(menu -> {
            if (Constants.ROOT_ID.equals(menu.getParentId())) {
                menu.setParentId(menu.getSubsystemId());
            }
        });

        return ResultUtil.successResult(TreeUtil.buildTree(
                "菜单树",
                new Tree(subsystemInfo, subsystemList),
                new Tree(portalInfo, portalList),
                new Tree(menuInfo, subsystemMenuList),
                new Tree(menuInfo, portalMenuList)));
    }

//    @PostMapping("/save")
//    public String save(@RequestBody MenuBO bo) {
//        return ResultUtil.saveResult(menuService.save(bo), bo);
//    }

    @PostMapping("/updateParentId")
    public String updateParentId(@RequestBody MenuBO bo) {
        if (Tool.isBlank(bo.getParentId())) {
            bo.setParentId(Constants.ROOT_ID);
        }
        if (bo.getId().equals(bo.getParentId())) {
            return ResultUtil.failureResult("不能移动到此目录！");
        }
        if (menuService.isParent(bo.getParentId(), bo.getId())) {
            return ResultUtil.failureResult("不允许移动到此子菜单下");
        }
        
        return ResultUtil.saveResult(menuService.updateParentId(bo), bo);
    }

    @PostMapping("/queryBy")
    public String queryBy(@RequestBody MenuBO bo) {
        return ResultUtil.successResult(menuService.queryBy(bo.getId()));
    }

    @PostMapping("/delete")
    public String delete(@RequestBody MenuBO bo) {
        return ResultUtil.deleteResult(menuService.delete(bo));
    }

    @PostMapping(value = "/exportData")
    public void exportData(HttpServletResponse response, @RequestBody MenuBO bo) {
        List<MenuBO> menuList = Collections.emptyList();
        if (bo.getIds() != null && bo.getIds().length > 0) {
            MenuBO menu = new MenuBO();
            menu.setIds(bo.getIds());
            menuList = menuService.queryList(menu);
        }
        String fileName = "menu-" + DateUtil.format(new Date(), "dd-HH-mm-ss") + ".dat";
        FileUtil.downloadContent(response, fileName, AESUtil.encrypt(GsonUtil.toJson(menuList)));
    }

    @PostMapping(value = "/importData")
    public String importData(MenuBO bo) {
        if (bo.getFile() == null) {
            return ResultUtil.failureResult("请选择上传文件！");
        }

        try {
            String content = new String(bo.getFile().getBytes(), StandardCharsets.UTF_8);
            Type type = new TypeToken<List<MenuBO>>(){}.getType();
            menuService.saveList(GsonUtil.fromJson(AESUtil.decrypt(content), type));
            return ResultUtil.successResult("导入菜单成功。");
        } catch (Exception e) {
            logger.error("文件解释出错！", e);
            return ResultUtil.failureResult("文件解释出错！");
        }
    }
}
